package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.dao.entity.UserRevStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocRevDO;
import com.cskaoyan.wordmemorize.dao.mapper.UserRevStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocRevMapper;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.DownLoadUserReviewDTO;
import com.cskaoyan.wordmemorize.dto.app.UserReviewStatisticsDTO;
import com.cskaoyan.wordmemorize.dto.app.UserVocRevDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserReviewDataCommand;
import com.cskaoyan.wordmemorize.request.UserReviewStatisticsCommand;
import com.cskaoyan.wordmemorize.request.UserVocRevCommand;
import com.cskaoyan.wordmemorize.service.UserReviewService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserReviewServiceImpl implements UserReviewService {

    @Resource
    private UserVocRevMapper userVocRevMapper;

    @Resource
    private UserRevStatisticsMapper userRevStatisticsMapper;

    /**
     * 上传APP端复习数据
     *
     * @param command 用户复习数据
     * @param userId  用户ID
     */
    @Override
    @Transactional
    public void synchronizeUserReviewData(UserReviewDataCommand command, Long userId) {
        // 从前端给的UserReviewDataCommand中包含：
        // 1. 用户复习统计数据(以天为单位) UserReviewStatisticsCommand revStatisticsCommand
        // 2. 用户已选单词（包括单词的复习情况） List<UserVocRevCommand> vocRevCommands

        // ======================= 1. 处理用户复习统计数据 =======================
        // 从前端给的UserReviewDataCommand中取出 用户复习统计数据（以天为单位）
        if (command.getRevStatisticsCommand() != null) {
            UserReviewStatisticsCommand statsCommand = command.getRevStatisticsCommand();

            // 检查数据库中是否已存在该日期的统计数据
            LambdaQueryWrapper<UserRevStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper
                    .eq(UserRevStatisticsDO::getUserId, userId)
                    .eq(UserRevStatisticsDO::getReviewDate, statsCommand.getReviewDate());
            UserRevStatisticsDO existingStats = userRevStatisticsMapper.selectOne(queryWrapper);

            // 如果已存在
            if (existingStats != null) {
                // 更新已有的统计数据
                existingStats.setVocNewCount(statsCommand.getVocNewCount());
                existingStats.setVocReviewCount(statsCommand.getVocReviewCount());
                existingStats.setTotalCount(statsCommand.getTotalCount());
                existingStats.setForgetCount(statsCommand.getForgetCount());
                existingStats.setUncertainCount(statsCommand.getUncertainCount());
                existingStats.setKnownCount(statsCommand.getKnownCount());
                existingStats.setSimpleCount(statsCommand.getSimpleCount());

                // 处理学习时间，将字符串转为Long
                if (statsCommand.getStudyTime() != null && !statsCommand.getStudyTime().isEmpty()) {
                    try {
                        existingStats.setStudyTime(Long.parseLong(statsCommand.getStudyTime()));
                    } catch (NumberFormatException e) {
                        // 如果转换失败，保持原值不变
                    }
                }
                // 执行更新
                userRevStatisticsMapper.updateById(existingStats);

            } else {
                // 如果不存在，即首次上传，创建新的统计数据
                UserRevStatisticsDO newStats = new UserRevStatisticsDO();

                newStats.setUserId(userId);
                newStats.setVocNewCount(statsCommand.getVocNewCount());
                newStats.setVocReviewCount(statsCommand.getVocReviewCount());
                newStats.setTotalCount(statsCommand.getTotalCount());
                newStats.setForgetCount(statsCommand.getForgetCount());
                newStats.setUncertainCount(statsCommand.getUncertainCount());
                newStats.setKnownCount(statsCommand.getKnownCount());
                newStats.setSimpleCount(statsCommand.getSimpleCount());
                newStats.setReviewDate(statsCommand.getReviewDate());

                // 处理学习时间
                // 如果学习时间数据存在，String转换为Long
                if (statsCommand.getStudyTime() != null && !statsCommand.getStudyTime().isEmpty()) {
                    try {
                        newStats.setStudyTime(Long.parseLong(statsCommand.getStudyTime()));
                    } catch (NumberFormatException e) {
                        newStats.setStudyTime(0L); // 如果转换出错，设置为0
                    }
                } else {
                    newStats.setStudyTime(0L); // 如果学习时间数据为空，设置为0
                }

                // 执行插入
                userRevStatisticsMapper.insert(newStats);
            }
        }


        // ======================= 2. 处理用户单词复习数据 =======================
        // // 从前端给的UserReviewDataCommand中取出 用户已选单词（包括单词的复习情况）
        if (command.getVocRevCommands() != null && !command.getVocRevCommands().isEmpty()) {
            // 遍历单词复习数据
            for (UserVocRevCommand vocRevCommand : command.getVocRevCommands()) {

                // 从String转换为Long
                long vocId;

                try {
                    vocId = Long.parseLong(vocRevCommand.getVocId());
                } catch (NumberFormatException e) {
                    // 如果转换失败，跳过该条记录
                    continue;
                }

                // 查找是否已存在该单词的复习记录
                LambdaQueryWrapper<UserVocRevDO> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper
                        .eq(UserVocRevDO::getUserId, userId)
                        .eq(UserVocRevDO::getVocId, vocId);
                UserVocRevDO existingRev = userVocRevMapper.selectOne(queryWrapper);

                // 如果已存在
                if (existingRev != null) {
                    // 更新已有的复习记录
                    existingRev.setFactor(vocRevCommand.getFactor());
                    existingRev.setReviewInterval(vocRevCommand.getReviewInterval());
                    existingRev.setNextReviewDate(vocRevCommand.getNextReviewDate());
                    existingRev.setType(vocRevCommand.getType());
                    existingRev.setFamiliarity(vocRevCommand.getFamiliarity());
                    existingRev.setConsecutiveFailCount(vocRevCommand.getConsecutiveFailCount());

                    // 更新总复习次数
                    if (existingRev.getTotalReview() == null) {
                        existingRev.setTotalReview(1); // 如果总复习次数为空，设置为1
                    } else {
                        existingRev.setTotalReview(existingRev.getTotalReview() + 1); // 不为空，增加1
                    }

                    // 执行更新
                    userVocRevMapper.updateById(existingRev);
                }
            }
        }
    }


    /**
     * APP端下载复习数据(首次登录时)
     *
     * @param pageRequest 分页请求
     * @param userId      用户ID
     * @return DownLoadUserReviewDTO 下载的用户的所有单词复习数据
     */
    @Override
    public DownLoadUserReviewDTO downloadUserReviewData(PageRequest pageRequest, Long userId) {
        // DownLoadUserReviewDTO 内包含：
        // 1.用户已选单词(复习)数据 PageDTO<UserVocRevDTO>
        // 2.用户以天为单位的复习统计数据数据 PageDTO<UserReviewStatisticsDTO>
        // 因此需要进行两部分查询然后组装
        DownLoadUserReviewDTO result = new DownLoadUserReviewDTO();


        // ==================== 1. 获取用户已选单词复习数据 PageDTO<UserVocRevDTO> ====================
        Page<UserVocRevDO> vocRevPage = new Page<>(
                pageRequest.getPageNum() != null ? pageRequest.getPageNum() : 1,
                pageRequest.getCount() != null ? pageRequest.getCount() : 10
        );

        // 构建查询请求
        LambdaQueryWrapper<UserVocRevDO> vocRevQueryWrapper = new LambdaQueryWrapper<>();
        vocRevQueryWrapper.eq(UserVocRevDO::getUserId, userId);
        // 执行分页查询，查询 已选单词复习数据
        Page<UserVocRevDO> vocRevResult = userVocRevMapper.selectPage(vocRevPage, vocRevQueryWrapper);

        // 转换为DTO
        List<UserVocRevDTO> vocRevDTOList = vocRevResult.getRecords().stream().map(vocRev -> {
            // 为每个查询结果创建一个新的UserVocRevDTO
            UserVocRevDTO dto = new UserVocRevDTO();
            // 封装内容
            dto.setId(String.valueOf(vocRev.getId()));
            dto.setVocId(String.valueOf(vocRev.getVocId()));
            dto.setUserId(String.valueOf(vocRev.getUserId()));
            dto.setFactor(vocRev.getFactor());
            dto.setReviewInterval(vocRev.getReviewInterval());
            dto.setNextReviewDate(vocRev.getNextReviewDate());
            dto.setType(vocRev.getType());
            dto.setFamiliarity(vocRev.getFamiliarity());
            dto.setConsecutiveFailCount(vocRev.getConsecutiveFailCount());
            dto.setTotalReview(vocRev.getTotalReview());

            return dto;

        }).collect(Collectors.toList());

        // 将DTO封装到分页对象
        PageDTO<UserVocRevDTO> vocRevPageDTO = new PageDTO<>();
        vocRevPageDTO.setPageList(vocRevDTOList); // 设置分页数据
        vocRevPageDTO.setTotalCount(vocRevResult.getTotal()); // 设置总条数

        // 将PageDTO<UserVocRevDTO>封装到DownLoadUserReviewDTO
        result.setUserVocRevPage(vocRevPageDTO);


        // ================ 2. 获取用户以天为单位的复习统计数据 PageDTO<UserReviewStatisticsDTO> ================
        // 构建分页查询请求
        Page<UserRevStatisticsDO> statsPage = new Page<>(
                pageRequest.getPageNum() != null ? pageRequest.getPageNum() : 1,
                pageRequest.getCount() != null ? pageRequest.getCount() : 10
        );

        // 构建查询请求
        LambdaQueryWrapper<UserRevStatisticsDO> statsQueryWrapper = new LambdaQueryWrapper<>();
        statsQueryWrapper.eq(UserRevStatisticsDO::getUserId, userId)
                .orderByDesc(UserRevStatisticsDO::getReviewDate); // 按照复习日期降序

        // 执行查询，查询 以天为单位的复习统计数据
        Page<UserRevStatisticsDO> statsResult = userRevStatisticsMapper.selectPage(statsPage, statsQueryWrapper);

        // 转换为DTO
        List<UserReviewStatisticsDTO> statsDTOList = statsResult.getRecords().stream().map(stats -> {
            // 为每个查询结果创建一个新的UserReviewStatisticsDTO
            UserReviewStatisticsDTO dto = new UserReviewStatisticsDTO();
            // 封装内容
            dto.setId(String.valueOf(stats.getId()));
            dto.setUserId(String.valueOf(stats.getUserId()));
            dto.setVocNewCount(stats.getVocNewCount());
            dto.setVocReviewCount(stats.getVocReviewCount());
            dto.setTotalCount(stats.getTotalCount());
            dto.setForgetCount(stats.getForgetCount());
            dto.setUncertainCount(stats.getUncertainCount());
            dto.setKnowCount(stats.getKnownCount());
            dto.setSimpleCount(stats.getSimpleCount());
            dto.setStudyTime(stats.getStudyTime() != null ? String.valueOf(stats.getStudyTime()) : "0");
            dto.setReviewDate(stats.getReviewDate());

            return dto;

        }).collect(Collectors.toList());

        // 将DTO封装到分页对象
        PageDTO<UserReviewStatisticsDTO> statsPageDTO = new PageDTO<>();
        statsPageDTO.setPageList(statsDTOList); // 设置分页数据
        statsPageDTO.setTotalCount(statsResult.getTotal()); // 设置总条数

        // 将PageDTO<UserReviewStatisticsDTO>封装到DownLoadUserReviewDTO
        result.setUserReviewStatisticsPage(statsPageDTO);

        // 返回最终的DownLoadUserReviewDTO
        return result;
    }


    /**
     * APP端添加复习单词
     *
     * @param vocIds 单词ID列表
     * @param userId 用户ID
     */
    @Override
    @Transactional
    public void addUserRovRev(List<Long> vocIds, Long userId) {
        // 因为前端即使没有选择单词也可以点击加入记忆按钮发送请求，因此需要先判断列表是否为空
        if (vocIds == null || vocIds.isEmpty()) {
            throw new BusinessException("单词列表为空", ResultCodeEnum.PARAM_ERROR.getCode());
        }

        LocalDate now = LocalDate.now();

        for (Long vocId : vocIds) {
            // 检查是否已经存在该单词的复习记录
            LambdaQueryWrapper<UserVocRevDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserVocRevDO::getUserId, userId)
                    .eq(UserVocRevDO::getVocId, vocId);

            UserVocRevDO existingRev = userVocRevMapper.selectOne(queryWrapper);

            if (existingRev == null) {
                // 创建新的复习记录
                UserVocRevDO newRev = new UserVocRevDO();

                newRev.setUserId(userId);
                newRev.setVocId(vocId);
                newRev.setFactor(1.4); // 默认易度因子
                newRev.setReviewInterval(1); // 默认复习间隔为1天
                newRev.setNextReviewDate(now.plusDays(1)); // 下次复习时间为明天
                newRev.setType(0); // 0表示已选未学
                newRev.setFamiliarity(null); // 初始熟悉度为空
                newRev.setConsecutiveFailCount(0); // 初始连续失败次数为0
                newRev.setTotalReview(0); // 初始总复习次数为0

                userVocRevMapper.insert(newRev);
            }
            // 如果已存在，则不做任何操作，保持原有记录
        }
    }
}
